package com.mdd.front.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.easemob.im.server.model.EMUser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mdd.common.entity.UserFriend;
import com.mdd.common.entity.distribution.Distribution;
import com.mdd.common.entity.user.User;
import com.mdd.common.entity.user.UserAuth;
import com.mdd.common.enums.NoticeEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.UserFriendMapper;
import com.mdd.common.mapper.distribution.DistributionMapper;
import com.mdd.common.mapper.user.UserAuthMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.plugin.notice.NoticeCheck;
import com.mdd.common.plugin.wechat.WxMnpDriver;
import com.mdd.common.util.ConfigUtils;
import com.mdd.common.util.HttpUtils;
import com.mdd.common.util.IpUtils;
import com.mdd.common.util.MapUtils;
import com.mdd.common.util.RedisUtils;
import com.mdd.common.util.StringUtils;
import com.mdd.common.util.TimeUtils;
import com.mdd.common.util.ToolUtils;
import com.mdd.common.util.em.EMServiceUtil;
import com.mdd.front.cache.ScanLoginCache;
import com.mdd.front.service.IDistributionService;
import com.mdd.front.service.ILoginService;
import com.mdd.front.vo.login.LoginTokenVo;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpOAuth2ServiceImpl;

/**
 * 登录服务实现类
 */
@Service
public class LoginServiceImpl implements ILoginService {

	@Resource
	UserMapper userMapper;

	@Resource
	UserAuthMapper userAuthMapper;

	@Resource
	IDistributionService iDistributionService;

	@Resource
	RedisUtils redisUtils;

	@Autowired
	private EMServiceUtil eMServiceUtil;
	@Autowired
	private UserFriendMapper userFriendMapper;
	@Autowired
	private DistributionMapper distributionMapper;


	private String exampleCode = "518186";
	private String defHeadPic = "https://kdkdkd.oss-cn-shanghai.aliyuncs.com/108.png";

	/**
	 * 注册账号
	 *
	 * @author fzr
	 * @param username 账号
	 * @param password 密码
	 * @param terminal 总端
	 */
	@Override
	public void register(String username, String password, Integer terminal, String inviteCode) {
		User model = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,sn,username")
				.eq("username", username)
				.eq("is_delete", 0)
				.eq("is_close", 0)
				.last("limit 1"));

		Assert.isNull(model, "账号已存在,换一个吧!");

		Integer sn  = this.__generateSn();
		String salt = ToolUtils.randomString(5);
		String pwd  = ToolUtils.makeMd5(password+salt);
		// 邀请码
		String code = userMapper.randMakeOrderSn("code");

		User user = new User();
		user.setSn(sn);
		user.setNickname("用户"+sn);
		user.setUsername(username);
		user.setPassword(pwd);
		user.setSalt(salt);
		user.setAvatar(defHeadPic);
		user.setChannel(terminal);
		user.setIsNew(1);
		user.setCreateTime(System.currentTimeMillis() / 1000);
		user.setUpdateTime(System.currentTimeMillis() / 1000);
		user.setCode(code);
		user.setAncestorRelation("");
		userMapper.insert(user);

		// 分销信息
		iDistributionService.addDistributionData(user.getId());
		// 绑定邀请人及上级
		if (StringUtils.isNotBlank(inviteCode)) {
			//            iDistributionService.bindInviter(user.getId(), inviteCode);
			//            if (iDistributionService.checkAbleBindLeader(user.getId(), inviteCode)) {
			//                iDistributionService.bindLeader(user.getId(), inviteCode);
			//            }
			// 绑定关系
			bindRelation(user.getId(), inviteCode);
		}
	}

	/**
	 * 账号登录
	 *
	 * @author fzr
	 * @param username 账号
	 * @param password 密码
	 * @return LoginTokenVo
	 */
	@Override
	public LoginTokenVo accountLogin(String mobile, String mobileCode, String inviteCode,Integer terminal) {
		boolean right = false;
		Object savedMobile = RedisUtils.get("MOBILE_CODE_"+ 1 + "_" + mobileCode);
		if (savedMobile != null && mobile.equals(savedMobile.toString())) {
			right = true;
		}
		if(exampleCode.equals(mobileCode)){
			right = true;
		}
		Assert.isFalse(!right, "验证码不一致");
		User user = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,username,password,salt,mobile,is_disable,is_new,em_username,nickname,mobile")
				.eq("mobile", mobile)
				.eq("is_delete", 0)
				.eq("is_close",0)
				.last("limit 1"));
		if(null == user) { // 注册
			Integer sn  = this.__generateSn();
			String salt = ToolUtils.randomString(5);
			String pwd  = ToolUtils.makeMd5("123456"+salt);
			// 邀请码
			String code = userMapper.randMakeOrderSn("code");
			user = new User();
			user.setSn(sn);
			user.setNickname("用户"+sn);
			user.setMobile(mobile);
			user.setUsername(mobile);
			user.setPassword(pwd);
			user.setSalt(salt);
			user.setAvatar(defHeadPic);
			user.setChannel(terminal);
			user.setIsNew(1);
			user.setCreateTime(System.currentTimeMillis() / 1000);
			user.setUpdateTime(System.currentTimeMillis() / 1000);
			user.setCode(code);
			user.setAncestorRelation("");
			userMapper.insert(user);
			// 分销信息
			iDistributionService.addDistributionData(user.getId());
			// 绑定邀请人及上级
			if (StringUtils.isNotBlank(inviteCode)) {
				//               iDistributionService.bindInviter(user.getId(), inviteCode);
				//               if (iDistributionService.checkAbleBindLeader(user.getId(), inviteCode)) {
				//                   iDistributionService.bindLeader(user.getId(), inviteCode);
				//               }
				// 绑定关系
				bindRelation(user.getId(), inviteCode);
			}
			// 创建环信账号
			String nickName = this.__EMUserName();
			EMUser createUser = eMServiceUtil.createUser(nickName);
			Assert.notNull(createUser, "登录失败");
			user.setEmUsername(createUser.getUsername());
			user.setEmPassword(createUser.getUsername());
			userMapper.updateById(user);
			// 绑定通讯里的用户信息
		}else if(StringUtils.isEmpty(user.getEmUsername())){
			// 创建环信账号
			String nickName = this.__EMUserName();
			EMUser createUser = eMServiceUtil.createUser(nickName);
			Assert.notNull(createUser, "登录失败");
			user.setEmUsername(createUser.getUsername());
			user.setEmPassword(createUser.getUsername());
			userMapper.updateById(user);
		}
		// 绑定userId
		//       UserFriend userFriend = userFriendMapper.selectOne(new LambdaQueryWrapper<UserFriend>().eq(UserFriend::getPhone, mobile).select(UserFriend::getId,UserFriend::getPhone
		//    		   ,UserFriend::getUserId));
		//       if(null != userFriend) {
		//    	   if(null == userFriend.getUserId()) {
		//    		   userFriend.setUserId(user.getId());
		//        	   userFriendMapper.updateById(userFriend);
		//    	   }
		//       }else {
		//    	   userFriend = new UserFriend();
		//    	   userFriend.setUserId(user.getId());
		//    	   userFriend.setName(user.getNickname());
		//    	   userFriend.setPhone(user.getMobile());
		//    	   userFriend.setCreateTime(System.currentTimeMillis() / 1000);
		//    	   userFriendMapper.insert(userFriend);
		//       }
		Integer userId = user.getId();
		List<UserFriend> list = userFriendMapper.selectList(new LambdaQueryWrapper<UserFriend>().eq(UserFriend::getPhone, mobile).select(UserFriend::getId,UserFriend::getUid,UserFriend::getPhone
				,UserFriend::getUserId));
		if(CollectionUtil.isNotEmpty(list)) {
			list.stream().forEach(friend ->{
				if(null == friend.getUserId()) {
					friend.setUserId(userId);
					friend.setUpdateTime(TimeUtils.timestamp());
					userFriendMapper.updateById(friend);


					//添加第二条记录
					UserFriend userFriendOther = new UserFriend();
					User userOther = userMapper.selectOne(new QueryWrapper<User>()
							.eq("id", friend.getUid())
							.last("limit 1"));
					userFriendOther.setUid(friend.getUserId());
					userFriendOther.setUserId(friend.getUid());
					userFriendOther.setCreateTime(System.currentTimeMillis() / 1000);
					userFriendOther.setUpdateTime(System.currentTimeMillis() / 1000);
					userFriendOther.setName(userOther.getNickname());
					userFriendOther.setPhone(userOther.getMobile());
					userFriendOther.setAddress(userOther.getAddress());
					userFriendMapper.insert(userFriendOther);




				}
			});
		}else {
			UserFriend userFriend = new UserFriend();
			userFriend.setUserId(userId);
			userFriend.setName(user.getNickname());
			userFriend.setPhone(user.getMobile());
			userFriend.setCreateTime(TimeUtils.timestamp());
			userFriendMapper.insert(userFriend);
		}

		return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), terminal,user.getEmUsername());
	}

	/**
	 * 	绑定上下级关系
	 * @param userId			用户ID
	 * @param inviteCode		邀请码
	 */
	private void bindRelation(Integer userId,String inviteCode) {
		User user = userMapper.selectById(userId);

		if (ObjectUtils.isEmpty(user)) {
			return;
		}
		if(user.getFirstLeader() > 0) {
			return;
		}
		User inviter = userMapper.selectOne(new QueryWrapper<User>()
				.eq("code", inviteCode));

		if (ObjectUtils.isEmpty(inviter)) {
			return;
		}
		user.setFirstLeader(inviter.getId());
		if(inviter.getFirstLeader() > 0) {
			user.setSecondLeader(inviter.getFirstLeader());
		}
//		int flag = 0;
//		// 查询用户等级
//		if(checkLevle(inviter.getId())) {
//			flag = 1;
//			user.setFirstLeader(inviter.getId());
//			if(inviter.getFirstLeader() > 0) {
//				user.setSecondLeader(inviter.getFirstLeader());
//			}
//		}
//		if(0 == flag) {
//			if(inviter.getFirstLeader() > 0) {
//				if(checkLevle(inviter.getFirstLeader())) {
//					user.setFirstLeader(inviter.getFirstLeader());
//					user.setSecondLeader(inviter.getSecondLeader());
//				}else {
//					seekSuperior(user, inviter.getSecondLeader());
//				}
//			}
//		}
		user.setInviterId(inviter.getId());
		userMapper.updateById(user);
	}


	int i = 0;
	private void seekSuperior(User user,Integer secondLeader) {
		if(secondLeader > 0) {
			if(checkLevle(secondLeader)) {
				user.setFirstLeader(secondLeader);
				User second = userMapper.selectOne(new QueryWrapper<User>()
						.eq("id", secondLeader));
				if(null != second && second.getFirstLeader() > 0) {
					user.setSecondLeader(second.getFirstLeader());
				}
			}else {
				User second = userMapper.selectOne(new QueryWrapper<User>()
						.eq("id", secondLeader));
				if(second.getFirstLeader() > 0) {
					if(checkLevle(second.getFirstLeader())) {
						user.setFirstLeader(second.getFirstLeader());
						user.setSecondLeader(second.getSecondLeader());
					}
				}else {
					i++;
					if(i < 3) {
						seekSuperior(user, second.getSecondLeader());
					}
				}
			}
		}
	}

	private boolean checkLevle(Integer userId) {
		Distribution distributionFirst = distributionMapper.selectOne(new LambdaQueryWrapper<Distribution>().eq(Distribution::getUserId, userId));
		if(null != distributionFirst && distributionFirst.getLevelId() > 2 && distributionFirst.getExpireTime() > TimeUtils.timestamp()) {
			return true;
		}
		return false;
	}

	/**
	 * 手机号登录
	 *
	 * @author fzr
	 * @param mobile 手机号
	 * @param code 验证码
	 * @return LoginTokenVo
	 */
	@Override
	public LoginTokenVo mobileLogin(String mobile, String code, Integer terminal) {
		// 校验验证码
		int sceneCode = NoticeEnum.LOGIN_CODE.getCode();
		if (!NoticeCheck.verify(sceneCode, code)) {
			throw new OperateException("验证码错误!");
		}

		// 查询手机号
		User user = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,username,mobile,is_disable,is_new,em_username")
				.eq("mobile", mobile)
				.eq("is_delete", 0)
				.eq("is_close",0)
				.last("limit 1"));

		Assert.notNull(user, "账号不存在!");
		Assert.isFalse(user.getIsDisable() != 0, "账号已禁用!");

		return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), terminal,user.getEmUsername());
	}

	/**
	 * 微信小程序登录
	 *
	 * @author fzr
	 * @param code 编码
	 * @param terminal 终端
	 * @return LoginTokenVo
	 */
	@Override
	@Transactional
	public LoginTokenVo mnpLogin(String code, Integer terminal, String inviteCode) {
		try {
			//        	 WxMaService wxMaService = WxMnpDriver.mnp();
			//             WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo(code);
			//             String openId = sessionResult.getOpenid();
			//             String uniId = sessionResult.getUnionid();
			//             String unionId = uniId;
			//             System.out.println("openId:"+openId);
			JSONObject json = getopenid2(code);
			System.out.println("微信登录返回参数："+json);
			String openId = json.getString("openid");
			String uniId = json.getString("unionid");
			String unionId = uniId;
			return this.__wxLoginHandle(openId, unionId, "", "", terminal, inviteCode);
		} catch (Exception e) {
			throw new OperateException(e.getMessage());
		}
	}

	public JSONObject getopenid2(String code) {
		JSONObject jsonObject = new JSONObject();
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("appid", "wxac5ad4234319499d");
		params.put("secret", "3e5620b79041753e343f1be65da2c97f");
		params.put("grant_type", "authorization_code");
		params.put("code", code);
		String result = HttpUtil.get(
				"https://api.weixin.qq.com/sns/oauth2/access_token", params);
		if (result != null) {
			jsonObject = JSONObject.parseObject(result);
			return jsonObject;
		}
		return jsonObject;
	}

	public static void main(String[] args) throws ClientProtocolException, IOException {
		String code = "0c3xQ3100cwwcT1gYe300qxleM1xQ31Q"; // 从小程序端获取的登录凭证

		String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
				"wx03d3a4501c174a80", "b5ba2c574608a0fa9a3d3a2f31202a13", code);

		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpGet httpGet = new HttpGet(url);
		HttpResponse response = httpClient.execute(httpGet);
		String jsonResponse = EntityUtils.toString(response.getEntity());

		ObjectMapper objectMapper = new ObjectMapper();
		Map<String, String> result = objectMapper.readValue(jsonResponse, Map.class);
		String openid = result.get("openid");
		String sessionKey = result.get("session_key");

		System.out.println("openid: " + openid);
		System.out.println("session_key: " + sessionKey);
	}
	/**
	 * 公众号登录
	 *
	 * @author fzr
	 * @param code 编码
	 * @param terminal 终端
	 * @param inviteCode 邀请码
	 * @return LoginTokenVo
	 */
	@Override
	public LoginTokenVo officeLogin(String code, Integer terminal, String inviteCode) {
		try {
			WxMpService wxMpService = WxMnpDriver.oa();
			WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
			String uniId = wxOAuth2AccessToken.getUnionId();
			String openId  = wxOAuth2AccessToken.getOpenId();
			String unionId = uniId == null ? "0" : uniId;
			System.out.println("code" + code);
			System.out.println("terminal" + terminal);
			System.out.println("inviteCode" + inviteCode);
			System.out.println("uniId" + uniId);
			System.out.println("unionId" + unionId);
			System.out.println("openId" + openId);
			String avatar = defHeadPic;
			String nickname = "";
			try {
				String accessToken = wxOAuth2AccessToken.getAccessToken();
				String userInfoUri = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
				String userInfoUrl = String.format(userInfoUri, accessToken, openId);
				String resultInfo = HttpUtils.sendGet(userInfoUrl);
				Map<String, String> resultMap = MapUtils.jsonToMap(resultInfo);
				//avatar   = resultMap.get("headimgurl");
				nickname = resultMap.get("nickname");
				System.out.println("avatar" + avatar);
				System.out.println("nickname" + nickname);
			} catch (Exception ignored) {}

			return this.__wxLoginHandle(openId, unionId, avatar, nickname, terminal, inviteCode);
		} catch (WxErrorException e) {
			throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
		}
	}

	/**
	 * 公众号跳转url
	 *
	 * @author fzr
	 * @param url 连接
	 * @return String
	 */
	@Override
	public String oaCodeUrl(String url) {
		WxMpService wxMpService = WxMnpDriver.oa();
		WxMpOAuth2ServiceImpl wxMpOAuth2Service = new WxMpOAuth2ServiceImpl(wxMpService);
		return wxMpOAuth2Service.buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
	}

	/**
	 * 扫码链接
	 *
	 * @author fzr
	 * @param session session
	 * @return String
	 */
	@Override
	public String scanCodeUrl(String url, HttpSession session) {
		// 获取AppId
		String appId = ConfigUtils.get("op_channel", "appId", "");

		// 微信开放平台授权
		String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
				"?appid=%s" +
				"&redirect_uri=%s" +
				"&response_type=code" +
				"&scope=snsapi_login" +
				"&state=%s" +
				"#wechat_redirect";

		// 回调地址
		String redirectUrl = url;
		try {
			redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new OperateException(e.getMessage());
		}

		// 防止csrf攻击
		String state = ToolUtils.makeUUID().replaceAll("-", "");
		ScanLoginCache.set(session.getId(), state);

		//生成QrcodeUrl
		String format = String.format(baseUrl, appId, redirectUrl, state);
		String sendGet = HttpUtils.sendGet(format);
		System.out.println("扫码返回参数："+sendGet);
		return format;
	}

	/**
	 * 扫码登录
	 *
	 * @author fzr
	 * @param code 编码
	 * @param state 标识
	 * @param terminal 终端
	 * @param session 会话
	 */
	@Override
	public LoginTokenVo scanLogin(String code, String state, Integer terminal, HttpSession session, String inviteCode) {
		if (!ScanLoginCache.get(session.getId()).equals(state)) {
			throw new OperateException("二维码已失效或不存在,请重新操作");
		}

		// 得到配置和授权临时票据code
		String appId = ConfigUtils.get("op_channel", "appId", "");
		String appSecret = ConfigUtils.get("op_channel", "appSecret", "");

		//向认证服务器发送请求换取access_token
		String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
				"?appid=%s" +
				"&secret=%s" +
				"&code=%s" +
				"&grant_type=authorization_code";

		Map<String, String> resultMap;
		try {
			String accessTokenUrl = String.format(baseAccessTokenUrl, appId, appSecret, code);
			String result = HttpUtils.sendGet(accessTokenUrl);
			resultMap = MapUtils.jsonToMap(result);
		} catch (Exception e) {
			throw new OperateException("获取access_token失败:"+e.getMessage());
		}

		// 访问微信获取用户信息 (openId,unionId,昵称,头像等)
		String accessToken = resultMap.get("access_token");
		String openid = resultMap.get("openid");
		String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
		String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
		Map<String, String> userinfoMap;
		try {
			String resultUserInfo = HttpUtils.sendGet(userInfoUrl);
			userinfoMap = MapUtils.jsonToMap(resultUserInfo);
		} catch (Exception e) {
			throw new OperateException("获取用户信息失败:"+e.getMessage());
		}

		String openId  = userinfoMap.get("openid");
		String uniId   = userinfoMap.get("unionid");
		String unionId = uniId == null ? "0" : uniId;
		String avatar   = resultMap.getOrDefault("headimgurl", "");
		String nickname = resultMap.getOrDefault("nickname", "");
		return this.__wxLoginHandle(openId, unionId, defHeadPic, nickname, terminal, inviteCode);
	}

	/**
	 * 处理微信登录
	 *
	 * @param openId   (openId)
	 * @param unionId  (unionId)
	 * @param terminal (terminal)
	 * @param avatar   (用户头像)
	 * @param nickname (用户昵称)
	 * @return LoginTokenVo
	 */
	private LoginTokenVo __wxLoginHandle(String openId, String unionId, String avatar, String nickname, Integer terminal, String inviteCode) {
		// 查询授权
		UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
				.nested(wq->wq
						.eq("unionid", unionId).or()
						.eq("openid", openId)
						).last("limit 1"));

		// 查询用户
		User user = null;
		if (StringUtils.isNotNull(userAuth)) {
			user = userMapper.selectOne(new QueryWrapper<User>()
					.eq("is_delete", 0)
					.eq("is_close",0)
					.eq("id", userAuth.getUserId())
					.last("limit 1"));
		}

		// 创建用户
		if (StringUtils.isNull(user)) {
			Integer sn = this.__generateSn();
			String defaultAvatar = defHeadPic;
			String defaultNickname = "用户" + sn;
			String code = userMapper.randMakeOrderSn("code");

			//			if (StringUtils.isNotEmpty(avatar)) {
			//				try {
			//					Long time = System.currentTimeMillis();
			//					String date = TimeUtils.millisecondToDate(time, "yyyyMMdd");
			//					String name = ToolUtils.makeMd5(ToolUtils.makeUUID()+time) + ".jpg";
			//					String path = "avatar" + date + "/" + name;
			//					String savePath = YmlUtils.get("like.upload-directory") + path;
			//					ToolUtils.download(avatar, savePath);
			//					defaultAvatar = path;
			//				} catch (IOException ignored) {}
			//			}

			if (StringUtils.isNotEmpty(nickname)) {
				defaultNickname = nickname;
			}

			User model = new User();
			model.setSn(sn);
			model.setAvatar(defaultAvatar);
			model.setNickname(defaultNickname);
			model.setUsername("u" + sn);
			model.setChannel(terminal);
			model.setSex(0);
			model.setLastLoginIp(IpUtils.getHostIp());
			model.setLastLoginTime(System.currentTimeMillis() / 1000);
			model.setUpdateTime(System.currentTimeMillis() / 1000);
			model.setCreateTime(System.currentTimeMillis() / 1000);
			model.setIsNew(1);
			model.setCode(code);
			model.setAncestorRelation("");
			userMapper.insert(model);
			user = model;

			// 分销信息
			iDistributionService.addDistributionData(user.getId());

			// 创建环信账号
			String nickName = this.__EMUserName();
			EMUser createUser = eMServiceUtil.createUser(nickName);
			Assert.notNull(createUser, "登录失败");
			user.setEmUsername(createUser.getUsername());
			user.setEmPassword(createUser.getUsername());
			userMapper.updateById(user);

			// 绑定邀请人及上级
			if (StringUtils.isNotBlank(inviteCode)) {
				//                iDistributionService.bindInviter(user.getId(), inviteCode);
				//                if (iDistributionService.checkAbleBindLeader(user.getId(), inviteCode)) {
				//                    iDistributionService.bindLeader(user.getId(), inviteCode);
				//                }
				// 绑定关系
				bindRelation(user.getId(), inviteCode);
			}
		}else if(StringUtils.isEmpty(user.getEmUsername())){
			// 创建环信账号
			String nickName = this.__EMUserName();
			EMUser createUser = eMServiceUtil.createUser(nickName);
			Assert.notNull(createUser, "登录失败");
			user.setEmUsername(createUser.getUsername());
			user.setEmPassword(createUser.getUsername());
			userMapper.updateById(user);
		}

		// 终端授权
		UserAuth auth = userAuthMapper.selectOne(
				new QueryWrapper<UserAuth>()
				.eq("openid", openId)
				.eq("terminal", terminal)
				.last("limit 1"));

		// 创建授权
		if (StringUtils.isNull(auth)) {
			UserAuth authModel = new UserAuth();
			authModel.setUserId(user.getId());
			authModel.setUnionid(unionId);
			authModel.setOpenid(openId);
			authModel.setTerminal(terminal);
			authModel.setCreateTime(System.currentTimeMillis() / 1000);
			authModel.setUpdateTime(System.currentTimeMillis() / 1000);
			userAuthMapper.insert(authModel);
		} else if (StringUtils.isEmpty(auth.getUnionid())) {
			auth.setUnionid(unionId);
			auth.setUpdateTime(System.currentTimeMillis() / 1000);
			userAuthMapper.updateById(auth);
		}

		return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), terminal,user.getEmUsername());
	}

	/**
	 * 处理录令牌
	 *
	 * @author fzr
	 * @param userId 用户ID
	 * @param mobile 用户手机
	 * @param terminal 终端
	 * @return LoginTokenVo
	 */
	private LoginTokenVo __loginToken(Integer userId, String mobile, Integer isNew, Integer terminal,String emUsername) {
		System.out.println("进来token设置");
		// 实现账号登录
		StpUtil.kickout(userId, String.valueOf(terminal));
		StpUtil.login(userId, String.valueOf(terminal));

		// 更新登录信息
		User user = new User();
		user.setLastLoginIp(IpUtils.getHostIp());
		user.setLastLoginTime(System.currentTimeMillis() / 1000);
		userMapper.update(user, new QueryWrapper<User>().eq("id", userId));
		// 返回登录信息
		LoginTokenVo vo = new LoginTokenVo();
		vo.setId(userId);
		vo.setIsBindMobile(!StringUtils.isEmpty(mobile));
		vo.setToken(StpUtil.getTokenValue());
		vo.setIsNew(isNew);
		vo.setEmUsername(emUsername);
		vo.setEmPassword(emUsername);
		System.out.println("结束");
		return vo;
	}

	/**
	 * 生成用户编号
	 *
	 * @author fzr
	 * @return Integer
	 */
	private Integer __generateSn() {
		Integer sn;
		while (true) {
			sn = Integer.parseInt(ToolUtils.randomInt(8));
			User snModel = userMapper.selectOne(new QueryWrapper<User>()
					.select("id,sn")
					.eq("sn", sn)
					.last("limit 1"));
			if (snModel == null) {
				break;
			}
		}
		return sn;
	}

	/**
	 * 	生成 环信 username
	 * @param length
	 * @return
	 */
	public String __EMUserName() {
		String english ="abcdefghijklmnopqrstuvwxyz";
		String hybrid = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb=new StringBuffer();
		for(int i=0;i<6;i++){
			int number= random.nextInt(36);
			if(i == 0) {
				sb.append(english.charAt(random.nextInt(26)));
				continue;
			}
			sb.append(hybrid.charAt(number));
		}
		return sb.toString();

	}

	@Override
	public LoginTokenVo oneClickLogin(String mobile, String inviteCode, Integer terminal) {
		System.out.println("进来一键登录---------------");
		User user = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,username,password,salt,mobile,is_disable,is_new,em_username")
				.eq("mobile", mobile)
				.eq("is_delete", 0)
				.eq("is_close",0)
				.last("limit 1"));
		if(null == user) { // 注册
			Integer sn  = this.__generateSn();
			String salt = ToolUtils.randomString(5);
			String pwd  = ToolUtils.makeMd5("123456"+salt);
			// 邀请码
			String code = userMapper.randMakeOrderSn("code");
			user = new User();
			user.setSn(sn);
			user.setNickname("用户"+sn);
			user.setMobile(mobile);
			user.setUsername(mobile);
			user.setPassword(pwd);
			user.setSalt(salt);
			user.setAvatar(defHeadPic);
			user.setChannel(terminal);
			user.setIsNew(1);
			user.setCreateTime(System.currentTimeMillis() / 1000);
			user.setUpdateTime(System.currentTimeMillis() / 1000);
			user.setCode(code);
			user.setAncestorRelation("");
			userMapper.insert(user);
			// 分销信息
			iDistributionService.addDistributionData(user.getId());
			// 绑定邀请人及上级
			if (StringUtils.isNotBlank(inviteCode)) {
				//               iDistributionService.bindInviter(user.getId(), inviteCode);
				//               if (iDistributionService.checkAbleBindLeader(user.getId(), inviteCode)) {
				//                   iDistributionService.bindLeader(user.getId(), inviteCode);
				//               }
				// 绑定关系
				bindRelation(user.getId(), inviteCode);
			}
			// 创建环信账号
			String nickName = this.__EMUserName();
			EMUser createUser = eMServiceUtil.createUser(nickName);
			Assert.notNull(createUser, "登录失败");
			user.setEmUsername(createUser.getUsername());
			user.setEmPassword(createUser.getUsername());
			userMapper.updateById(user);
			// 绑定通讯里的用户信息
		}else if(StringUtils.isEmpty(user.getEmUsername())){
			// 创建环信账号
			String nickName = this.__EMUserName();
			EMUser createUser = eMServiceUtil.createUser(nickName);
			Assert.notNull(createUser, "登录失败");
			user.setEmUsername(createUser.getUsername());
			user.setEmPassword(createUser.getUsername());
			userMapper.updateById(user);
		}
		System.out.println("用户关联信息-------------");
		Integer userId = user.getId();
		List<UserFriend> list = userFriendMapper.selectList(new LambdaQueryWrapper<UserFriend>().eq(UserFriend::getPhone, mobile).select(UserFriend::getId,UserFriend::getUid,UserFriend::getPhone
				,UserFriend::getUserId));
		if(CollectionUtil.isNotEmpty(list)) {
			System.out.println("用户关联信息-------------0001");
			list.stream().forEach(friend ->{
				if(null == friend.getUserId()) {
					friend.setUserId(userId);
					friend.setUpdateTime(TimeUtils.timestamp());
					userFriendMapper.updateById(friend);

					//添加第二条记录
					UserFriend userFriendOther = new UserFriend();
					User userOther = userMapper.selectOne(new QueryWrapper<User>()
							.eq("id", friend.getUid())
							.last("limit 1"));
					userFriendOther.setUid(friend.getUserId());
					userFriendOther.setUserId(friend.getUid());
					userFriendOther.setCreateTime(System.currentTimeMillis() / 1000);
					userFriendOther.setUpdateTime(System.currentTimeMillis() / 1000);
					userFriendOther.setName(userOther.getNickname());
					userFriendOther.setPhone(userOther.getMobile());
					userFriendOther.setAddress(userOther.getAddress());
					userFriendMapper.insert(userFriendOther);
				}
			});
		}else {
			System.out.println("用户关联信息-------------0002");
			UserFriend userFriend = new UserFriend();
			userFriend.setUserId(userId);
			userFriend.setName(user.getNickname());
			userFriend.setPhone(user.getMobile());
			userFriend.setCreateTime(TimeUtils.timestamp());
			userFriendMapper.insert(userFriend);
		}
		
		return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), terminal,user.getEmUsername());
	}

	@Override
	public String getMnpCodeUrl(String url) {
		WxMaService mnp = WxMnpDriver.mnp();
		try {
			String accessToken = mnp.getAccessToken();
			JSONObject jsonParam = new JSONObject();
			jsonParam.put("path", url);
			String wxUrl = WxMaApiUrlConstants.Qrcode.CREATE_QRCODE_URL+"?access_token="+accessToken;
			InputStream inputStream = HttpUtils.doWXPost(wxUrl, jsonParam);
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int bytesRead;
			while ((bytesRead = inputStream.read(buffer)) != -1) {
				outputStream.write(buffer, 0, bytesRead);
			}
			byte[] bytes = outputStream.toByteArray();
			return Base64.encodeBase64String(bytes);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
}
